#include "resource_view_model.h"
#include <QDebug>
#include <algorithm>

namespace presentation {
namespace viewmodels {

// ==================== LiftListModel ====================

LiftListModel::LiftListModel(QObject* parent)
    : QAbstractListModel(parent)
{
}

int LiftListModel::rowCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent);
    return m_liftList.count();
}

QVariant LiftListModel::data(const QModelIndex& index, int role) const
{
    if (index.row() < 0 || index.row() >= m_liftList.count())
        return QVariant();

    const LiftData& lift = m_liftList[index.row()];

    switch (role) {
        case LiftNumRole: return lift.liftNum;
        case StatusRole: return lift.status;
        case CurrentFloorRole: return lift.currentFloor;
        case IsLockedRole: return lift.isLocked;
        case IsOnlineRole: return lift.isOnline;
        case LiftTypeRole: return lift.liftType;
        case AvailableFloorsRole: {
            QVariantList floors;
            for (int floor : lift.availableFloors) {
                floors.append(floor);
            }
            return floors;
        }
        default: return QVariant();
    }
}

QHash<int, QByteArray> LiftListModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[LiftNumRole] = "liftNum";
    roles[StatusRole] = "status";
    roles[CurrentFloorRole] = "currentFloor";
    roles[IsLockedRole] = "isLocked";
    roles[IsOnlineRole] = "isOnline";
    roles[LiftTypeRole] = "liftType";
    roles[AvailableFloorsRole] = "availableFloors";
    return roles;
}

QVariantMap LiftListModel::getLiftData(int row) const
{
    QVariantMap map;
    if (row < 0 || row >= m_liftList.count())
        return map;

    const LiftData& lift = m_liftList[row];
    map["liftNum"] = lift.liftNum;
    map["status"] = lift.status;
    map["currentFloor"] = lift.currentFloor;
    map["isLocked"] = lift.isLocked;
    map["isOnline"] = lift.isOnline;
    map["liftType"] = lift.liftType;

    QVariantList floors;
    for (int floor : lift.availableFloors) {
        floors.append(floor);
    }
    map["availableFloors"] = floors;

    return map;
}

QVariantList LiftListModel::getAvailableFloors(int liftNum) const
{
    QVariantList floors;
    for (const LiftData& lift : m_liftList) {
        if (lift.liftNum == liftNum) {
            for (int floor : lift.availableFloors) {
                floors.append(floor);
            }
            break;
        }
    }
    return floors;
}

void LiftListModel::updateData(const QList<std::shared_ptr<application::lift::BaseLift>>& lifts)
{
    beginResetModel();
    m_liftList.clear();

    for (const auto& lift : lifts) {
        if (!lift) continue;

        LiftData data;
        data.liftNum = lift->getLiftNum();
        data.isLocked = lift->isLocked();
        data.isOnline = (lift->getStatus() != application::lift::LiftStatus::Offline);

        // 状态转换
        switch (lift->getStatus()) {
            case application::lift::LiftStatus::Idle:
                data.status = "空闲";
                break;
            case application::lift::LiftStatus::Busy:
                data.status = "忙碌";
                break;
            case application::lift::LiftStatus::Error:
                data.status = "错误";
                break;
            case application::lift::LiftStatus::Offline:
                data.status = "离线";
                break;
            default:
                data.status = "未知";
                break;
        }

        // 类型转换
        switch (lift->getType()) {
            case application::lift::LiftType::HK:
                data.liftType = "小电梯";
                break;
            case application::lift::LiftType::JZ:
                data.liftType = "大电梯";
                break;
            case application::lift::LiftType::MKLM:
                data.liftType = "米克力美";
                break;
            default:
                data.liftType = "未知";
                break;
        }

        // 获取可用楼层
        auto floorInfos = lift->getAllFloorInfos();
        for (const auto& floorInfo : floorInfos) {
            data.availableFloors.append(floorInfo.floor);
        }

        // 当前楼层（从当前请求获取）
        const auto& currentReq = lift->currentRequest();
        data.currentFloor = currentReq.startFloor.floor;

        m_liftList.append(data);
    }

    endResetModel();
}

// ==================== AreaOccupancyModel ====================

AreaOccupancyModel::AreaOccupancyModel(QObject* parent)
    : QAbstractListModel(parent)
{
}

int AreaOccupancyModel::rowCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent);
    return m_areaList.count();
}

QVariant AreaOccupancyModel::data(const QModelIndex& index, int role) const
{
    if (index.row() < 0 || index.row() >= m_areaList.count())
        return QVariant();

    const AreaData& area = m_areaList[index.row()];

    switch (role) {
        case AreaIdRole: return area.areaId;
        case MapNameRole: return area.mapName;
        case FloorRole: return area.floor;
        case IsOccupiedRole: return area.isOccupied;
        case OccupiedByRole: return area.occupiedBy;
        case IsThirdPartyRole: return area.isThirdParty;
        case OccupationStateRole: return area.occupationState;
        default: return QVariant();
    }
}

QHash<int, QByteArray> AreaOccupancyModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[AreaIdRole] = "areaId";
    roles[MapNameRole] = "mapName";
    roles[FloorRole] = "floor";
    roles[IsOccupiedRole] = "isOccupied";
    roles[OccupiedByRole] = "occupiedBy";
    roles[IsThirdPartyRole] = "isThirdParty";
    roles[OccupationStateRole] = "occupationState";
    return roles;
}

QVariantMap AreaOccupancyModel::getAreaData(int row) const
{
    QVariantMap map;
    if (row < 0 || row >= m_areaList.count())
        return map;

    const AreaData& area = m_areaList[row];
    map["areaId"] = area.areaId;
    map["mapName"] = area.mapName;
    map["floor"] = area.floor;
    map["isOccupied"] = area.isOccupied;
    map["occupiedBy"] = area.occupiedBy;
    map["isThirdParty"] = area.isThirdParty;
    map["occupationState"] = area.occupationState;

    return map;
}

void AreaOccupancyModel::updateData(
    const QList<std::tuple<QString, int, std::shared_ptr<application::area::Area>>>& areas,
    const QList<application::third_area::ThirdBlockArea*>& thirdAreas)
{
    beginResetModel();
    m_areaList.clear();

    // 添加普通区域
    for (const auto& [mapName, floor, area] : areas) {
        if (!area) continue;

        AreaData data;
        data.areaId = area->getAreaId();
        data.mapName = mapName;
        data.floor = floor;
        data.isOccupied = area->isOccupied();
        data.isThirdParty = false;
        data.occupationState = data.isOccupied ? QStringLiteral("occupied") : QStringLiteral("idle");

        // 获取占用者
        auto occupyingAgvs = area->getOccupyingAgvIds();
        if (!occupyingAgvs.isEmpty()) {
            QStringList agvNames;
            for (int agvId : occupyingAgvs) {
                agvNames.append(QString("AGV%1").arg(agvId));
            }
            data.occupiedBy = agvNames.join(", ");
        } else {
            data.occupiedBy = "-";
        }

        m_areaList.append(data);
    }

    // 添加第三方区域
    for (auto* thirdArea : thirdAreas) {
        if (!thirdArea) continue;

        AreaData data;
        data.areaId = thirdArea->getAreaId();
        data.mapName = QString("楼层%1").arg(thirdArea->getFloor());
        data.floor = thirdArea->getFloor();
        data.isThirdParty = true;

        const int currentAgv = thirdArea->getCurrentOccupyAgvId();
        const int preAgv = thirdArea->getPreOccupyAgvId();
        const QString thirdVehicle = thirdArea->getThirdPartyVehicleId();

        if (currentAgv != -1) {
            data.isOccupied = true;
            data.occupationState = QStringLiteral("agvOccupied");
            data.occupiedBy = QString("AGV%1").arg(currentAgv);
        } else if (preAgv != -1) {
            data.isOccupied = true;
            data.occupationState = QStringLiteral("preOccupied");
            data.occupiedBy = QString("AGV%1 (预占)").arg(preAgv);
        } else if (!thirdVehicle.isEmpty()) {
            data.isOccupied = true;
            data.occupationState = QStringLiteral("thirdParty");
            data.occupiedBy = QString("第三方:%1").arg(thirdVehicle);
        } else {
            data.isOccupied = false;
            data.occupationState = QStringLiteral("idle");
            data.occupiedBy = "-";
        }

        m_areaList.append(data);
    }

    endResetModel();
}

// ==================== AutoDoorListModel ====================

AutoDoorListModel::AutoDoorListModel(QObject* parent)
    : QAbstractListModel(parent)
{
}

int AutoDoorListModel::rowCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent);
    return m_doorList.count();
}

QVariant AutoDoorListModel::data(const QModelIndex& index, int role) const
{
    if (index.row() < 0 || index.row() >= m_doorList.count())
        return QVariant();

    const AutoDoorData& door = m_doorList[index.row()];

    switch (role) {
        case DoorIdRole: return door.doorId;
        case FloorRole: return door.floor;
        case DeviceIdRole: return static_cast<qulonglong>(door.deviceId);
        case Point1Role: return door.point1;
        case Point2Role: return door.point2;
        case StateRole: return door.state;
        case IsOnlineRole: return door.isOnline;
        default: return QVariant();
    }
}

QHash<int, QByteArray> AutoDoorListModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[DoorIdRole] = "doorId";
    roles[FloorRole] = "floor";
    roles[DeviceIdRole] = "deviceId";
    roles[Point1Role] = "point1";
    roles[Point2Role] = "point2";
    roles[StateRole] = "state";
    roles[IsOnlineRole] = "isOnline";
    return roles;
}

QVariantMap AutoDoorListModel::getDoorData(int row) const
{
    QVariantMap map;
    if (row < 0 || row >= m_doorList.count())
        return map;

    const AutoDoorData& door = m_doorList[row];
    map["doorId"] = door.doorId;
    map["floor"] = door.floor;
    map["deviceId"] = static_cast<qulonglong>(door.deviceId);
    map["point1"] = door.point1;
    map["point2"] = door.point2;
    map["state"] = door.state;
    map["isOnline"] = door.isOnline;
    return map;
}

void AutoDoorListModel::updateData(
    const QList<application::auto_door::AutoDoorManager::DoorInfo>& doors)
{
    beginResetModel();
    m_doorList.clear();

    auto stateToText = [](application::auto_door::DoorState state) -> QString {
        switch (state) {
            case application::auto_door::DoorState::Closed: return "关闭";
            case application::auto_door::DoorState::Closing: return "正在关闭";
            case application::auto_door::DoorState::Open: return "打开";
            case application::auto_door::DoorState::Opening: return "正在打开";
            default: return "未知";
        }
    };

    for (const auto& info : doors) {
        AutoDoorData data;
        data.doorId = info.doorId;
        data.floor = info.floor;
        data.deviceId = info.deviceId;
        data.point1 = info.point1;
        data.point2 = info.point2;
        data.state = stateToText(info.state);
        data.isOnline = info.deviceOnline;
        m_doorList.append(data);
    }

    endResetModel();
}

// ==================== CallerListModel ====================

CallerListModel::CallerListModel(QObject* parent)
    : QAbstractListModel(parent)
{
}

int CallerListModel::rowCount(const QModelIndex& parent) const
{
    Q_UNUSED(parent);
    return m_callers.count();
}

QVariant CallerListModel::data(const QModelIndex& index, int role) const
{
    if (index.row() < 0 || index.row() >= m_callers.count()) {
        return QVariant();
    }

    const CallerData& caller = m_callers[index.row()];
    switch (role) {
        case CallerNumRole: return caller.callerNum;
        case TaskNameRole: return caller.taskName;
        case IsOnlineRole: return caller.isOnline;
        case LastTriggerRole: return caller.lastTriggerTime;
        case LastTriggerTextRole: return caller.lastTriggerText;
        default: return QVariant();
    }
}

QHash<int, QByteArray> CallerListModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[CallerNumRole] = "callerNum";
    roles[TaskNameRole] = "taskName";
    roles[IsOnlineRole] = "isOnline";
    roles[LastTriggerRole] = "lastTriggerTime";
    roles[LastTriggerTextRole] = "lastTriggerText";
    return roles;
}

void CallerListModel::updateData(const QList<application::caller::CallerRuntimeInfo>& callers)
{
    beginResetModel();
    m_callers.clear();

    auto makeDisplayText = [](const QDateTime& time) -> QString {
        if (!time.isValid()) {
            return QStringLiteral("未触发");
        }
        return time.toString("yyyy-MM-dd HH:mm:ss");
    };

    for (const auto& caller : callers) {
        CallerData data;
        data.callerNum = caller.callerNum;
        data.taskName = caller.taskName;
        data.isOnline = caller.isOnline;
        data.lastTriggerTime = caller.lastTriggerTime;
        data.lastTriggerText = makeDisplayText(caller.lastTriggerTime);
        m_callers.append(data);
    }

    endResetModel();
}

// ==================== ResourceViewModel ====================

ResourceViewModel::ResourceViewModel(
    std::shared_ptr<application::MapApplicationService> mapService,
    QObject* parent)
    : BaseViewModel(parent)
    , m_mapService(mapService)
    , m_liftListModel(new LiftListModel(this))
    , m_areaOccupancyModel(new AreaOccupancyModel(this))
    , m_autoDoorListModel(new AutoDoorListModel(this))
    , m_callerListModel(new CallerListModel(this))
    , m_refreshTimer(new QTimer(this))
{
    // 设置定时刷新（每5秒）
    m_refreshTimer->setInterval(5000);
    connect(m_refreshTimer, &QTimer::timeout, this, &ResourceViewModel::onRefreshTimer);
}

void ResourceViewModel::initialize()
{
    if (isInitialized()) {
        return;
    }

    setLoading(true);

    // 初始化数据
    refreshAllData();

    // 启动定时器
    m_refreshTimer->start();

    setInitialized(true);
    setLoading(false);
}

void ResourceViewModel::cleanup()
{
    m_refreshTimer->stop();
    m_connectedCallerManagers.clear();
    m_connectedAreaManagers.clear();
    m_connectedThirdAreaManagers.clear();
    setInitialized(false);
}

bool ResourceViewModel::callLift(int liftNum, int targetFloor)
{
    if (!m_mapService) {
        emit operationFailed("地图服务不可用");
        return false;
    }

    auto liftManager = m_mapService->getLiftManager();
    if (!liftManager) {
        emit operationFailed("电梯管理器不可用");
        return false;
    }

    auto lift = liftManager->getLift(liftNum);
    if (!lift) {
        emit operationFailed(QString("电梯 %1 不存在").arg(liftNum));
        return false;
    }

    // 呼叫电梯（这里简化处理，实际需要根据电梯类型调用不同的方法）
    bool success = false;
    lift->requestLiftCall(liftNum, 1, targetFloor, [this, &success]() {
        success = true;
        emit operationSuccess("电梯呼叫成功");
    });

    if (success) {
        refreshLiftData();
    }

    return success;
}

bool ResourceViewModel::openLiftDoor(int liftNum)
{
    if (!m_mapService) {
        emit operationFailed("地图服务不可用");
        return false;
    }

    auto liftManager = m_mapService->getLiftManager();
    if (!liftManager) {
        emit operationFailed("电梯管理器不可用");
        return false;
    }

    auto lift = liftManager->getLift(liftNum);
    if (!lift) {
        emit operationFailed(QString("电梯 %1 不存在").arg(liftNum));
        return false;
    }

    bool success = false;
    lift->requestDoorOpen(QString::number(liftNum), [this, &success]() {
        success = true;
        emit operationSuccess("电梯门已打开");
    });

    return success;
}

bool ResourceViewModel::closeLiftDoor(int liftNum)
{
    if (!m_mapService) {
        emit operationFailed("地图服务不可用");
        return false;
    }

    auto liftManager = m_mapService->getLiftManager();
    if (!liftManager) {
        emit operationFailed("电梯管理器不可用");
        return false;
    }

    auto lift = liftManager->getLift(liftNum);
    if (!lift) {
        emit operationFailed(QString("电梯 %1 不存在").arg(liftNum));
        return false;
    }

    bool success = false;
    lift->requestDoorClose(QString::number(liftNum), [this, &success]() {
        success = true;
        emit operationSuccess("电梯门已关闭");
    });

    return success;
}

bool ResourceViewModel::lockLift(int liftNum)
{
    if (!m_mapService) {
        emit operationFailed("地图服务不可用");
        return false;
    }

    auto liftManager = m_mapService->getLiftManager();
    if (!liftManager) {
        emit operationFailed("电梯管理器不可用");
        return false;
    }

    auto lift = liftManager->getLift(liftNum);
    if (!lift) {
        emit operationFailed(QString("电梯 %1 不存在").arg(liftNum));
        return false;
    }

    lift->lock();
    emit operationSuccess(QString("电梯 %1 已锁定").arg(liftNum));
    refreshLiftData();
    return true;
}

bool ResourceViewModel::unlockLift(int liftNum)
{
    if (!m_mapService) {
        emit operationFailed("地图服务不可用");
        return false;
    }

    auto liftManager = m_mapService->getLiftManager();
    if (!liftManager) {
        emit operationFailed("电梯管理器不可用");
        return false;
    }

    auto lift = liftManager->getLift(liftNum);
    if (!lift) {
        emit operationFailed(QString("电梯 %1 不存在").arg(liftNum));
        return false;
    }

    lift->unlock();
    emit operationSuccess(QString("电梯 %1 已解锁").arg(liftNum));
    refreshLiftData();
    return true;
}

bool ResourceViewModel::forceReleaseArea(const QString& areaId, int floor)
{
    if (!m_mapService) {
        emit operationFailed("地图服务不可用");
        return false;
    }

    auto areaManager = m_mapService->getAreaManager(floor);
    if (!areaManager) {
        emit operationFailed(QString("楼层 %1 的区域管理器不可用").arg(floor));
        return false;
    }

    auto area = areaManager->getArea(areaId);
    if (!area) {
        emit operationFailed(QString("区域 %1 不存在").arg(areaId));
        return false;
    }

    // 强制释放所有占用
    auto occupyingAgvs = area->getOccupyingAgvIds();
    for (int agvId : occupyingAgvs) {
        area->releaseOccupation(agvId);
    }

    emit operationSuccess(QString("区域 %1 已强制释放").arg(areaId));
    refreshAreaData();
    return true;
}

bool ResourceViewModel::forceReleaseThirdArea(const QString& areaId)
{
    if (!m_mapService) {
        emit operationFailed("地图服务不可用");
        return false;
    }

    auto thirdAreaManager = m_mapService->getThirdAreaManager(0);
    if (thirdAreaManager) {
        auto thirdArea = thirdAreaManager->getArea(areaId);
        if (thirdArea) {
            thirdArea->forceRelease();
            emit operationSuccess(QString("第三方区域 %1 已强制释放").arg(areaId));
            refreshAreaData();
            return true;
        }
    }

    emit operationFailed(QString("第三方区域 %1 不存在").arg(areaId));
    return false;
}

bool ResourceViewModel::openAutoDoor(int doorId)
{
    auto manager = ensureAutoDoorManager();
    if (!manager) {
        emit operationFailed("自动门管理器不可用");
        return false;
    }

    manager->openDoor(doorId);
    emit operationSuccess(QString("已发送开门指令：自动门 %1").arg(doorId));
    refreshAutoDoorData();
    return true;
}

bool ResourceViewModel::closeAutoDoor(int doorId)
{
    auto manager = ensureAutoDoorManager();
    if (!manager) {
        emit operationFailed("自动门管理器不可用");
        return false;
    }

    manager->closeDoor(doorId);
    emit operationSuccess(QString("已发送关门指令：自动门 %1").arg(doorId));
    refreshAutoDoorData();
    return true;
}

void ResourceViewModel::refreshLiftData()
{
    updateLiftList();
}

void ResourceViewModel::refreshAreaData()
{
    updateAreaList();
}

void ResourceViewModel::refreshAutoDoorData()
{
    updateAutoDoorList();
}

void ResourceViewModel::refreshCallerData()
{
    updateCallerList();
}

void ResourceViewModel::refreshAllData()
{
    updateLiftList();
    updateAreaList();
    updateAutoDoorList();
    updateCallerList();
    updateStatistics();
}

void ResourceViewModel::onRefreshTimer()
{
    if (!isInitialized()) {
        return;
    }

    refreshAllData();
}

void ResourceViewModel::onLiftStatusChanged()
{
    refreshLiftData();
}

void ResourceViewModel::onAreaOccupancyChanged()
{
    refreshAreaData();
}

void ResourceViewModel::updateLiftList()
{
    if (!m_mapService) {
        return;
    }

    auto liftManager = m_mapService->getLiftManager();
    if (!liftManager) {
        return;
    }

    auto lifts = liftManager->getAllLifts();
    m_liftListModel->updateData(lifts);

    int newCount = lifts.count();
    if (m_totalLiftCount != newCount) {
        m_totalLiftCount = newCount;
        emit totalLiftCountChanged();
    }
}

void ResourceViewModel::updateAreaList()
{
    if (!m_mapService) {
        return;
    }

    QList<std::tuple<QString, int, std::shared_ptr<application::area::Area>>> allAreas;
    QList<application::third_area::ThirdBlockArea*> allThirdAreas;
    QSet<application::third_area::ThirdAreaManager*> processedThirdManagers;

    // 收集所有楼层的区域
    const auto floors = m_mapService->getLoadedFloors();
    for (int floor : floors) {
        QString mapName = m_mapService->getMapNameForFloor(floor);
        if (mapName.isEmpty()) continue;

        auto areaManager = m_mapService->getAreaManager(floor);
        if (areaManager) {
            connectAreaManager(areaManager.get());
            auto areaIds = areaManager->getAllAreaIds();
            for (const QString& areaId : areaIds) {
                auto area = areaManager->getArea(areaId);
                if (area) {
                    allAreas.append(std::make_tuple(mapName, floor, area));
                }
            }
        }

        auto thirdAreaManager = m_mapService->getThirdAreaManager(floor);
        if (thirdAreaManager && !processedThirdManagers.contains(thirdAreaManager.get())) {
            connectThirdAreaManager(thirdAreaManager.get());
            auto thirdAreas = thirdAreaManager->getAllAreas();
            allThirdAreas.append(thirdAreas);
            processedThirdManagers.insert(thirdAreaManager.get());
        }
    }

    m_areaOccupancyModel->updateData(allAreas, allThirdAreas);

    int newTotalCount = allAreas.count() + allThirdAreas.count();
    if (m_totalAreaCount != newTotalCount) {
        m_totalAreaCount = newTotalCount;
        emit totalAreaCountChanged();
    }
}

void ResourceViewModel::updateStatistics()
{
    // 统计占用的区域数量
    int occupiedCount = 0;

    if (!m_mapService) {
        return;
    }

    QSet<application::third_area::ThirdAreaManager*> processedThirdManagers;
    const auto floors = m_mapService->getLoadedFloors();
    for (int floor : floors) {
        auto areaManager = m_mapService->getAreaManager(floor);
        if (areaManager) {
            auto areaIds = areaManager->getAllAreaIds();
            for (const QString& areaId : areaIds) {
                auto area = areaManager->getArea(areaId);
                if (area && area->isOccupied()) {
                    occupiedCount++;
                }
            }
        }

        auto thirdAreaManager = m_mapService->getThirdAreaManager(floor);
        if (thirdAreaManager && !processedThirdManagers.contains(thirdAreaManager.get())) {
            auto thirdAreas = thirdAreaManager->getAllAreas();
            for (auto* thirdArea : thirdAreas) {
                if (thirdArea && thirdArea->isOccupied()) {
                    occupiedCount++;
                }
            }
            processedThirdManagers.insert(thirdAreaManager.get());
        }
    }

    if (m_occupiedAreaCount != occupiedCount) {
        m_occupiedAreaCount = occupiedCount;
        emit occupiedAreaCountChanged();
    }
}

void ResourceViewModel::onAutoDoorStateChanged()
{
    updateAutoDoorList();
}

void ResourceViewModel::onAreaManagerSignal(const QString&)
{
    onAreaOccupancyChanged();
}

void ResourceViewModel::onThirdAreaSignal(const QString&, const QString&)
{
    onAreaOccupancyChanged();
}

std::shared_ptr<application::auto_door::AutoDoorManager> ResourceViewModel::ensureAutoDoorManager()
{
    if (m_autoDoorManager) {
        return m_autoDoorManager;
    }

    if (!m_mapService) {
        return nullptr;
    }

    m_autoDoorManager = m_mapService->getAutoDoorManager(m_mapService->getCurrentFloor());
    setupAutoDoorConnections();
    return m_autoDoorManager;
}

void ResourceViewModel::setupAutoDoorConnections()
{
    if (!m_autoDoorManager || m_autoDoorSignalsConnected) {
        return;
    }

    auto manager = m_autoDoorManager.get();
    m_autoDoorSignalsConnected = true;

    connect(manager, &application::auto_door::AutoDoorManager::doorAdded,
            this, &ResourceViewModel::onAutoDoorStateChanged);
    connect(manager, &application::auto_door::AutoDoorManager::doorRemoved,
            this, &ResourceViewModel::onAutoDoorStateChanged);
    connect(manager, &application::auto_door::AutoDoorManager::doorStateChanged,
            this, &ResourceViewModel::onAutoDoorStateChanged);
    connect(manager, &application::auto_door::AutoDoorManager::deviceOnline,
            this, &ResourceViewModel::onAutoDoorStateChanged);
    connect(manager, &application::auto_door::AutoDoorManager::deviceOffline,
            this, &ResourceViewModel::onAutoDoorStateChanged);
}

void ResourceViewModel::updateAutoDoorList()
{
    auto manager = ensureAutoDoorManager();
    QList<application::auto_door::AutoDoorManager::DoorInfo> doorInfos;
    if (manager) {
        doorInfos = manager->getDoorInfos();
    }

    m_autoDoorListModel->updateData(doorInfos);

    int newTotal = doorInfos.count();
    int onlineCount = 0;
    for (const auto& info : doorInfos) {
        if (info.deviceOnline) {
            ++onlineCount;
        }
    }

    if (m_totalAutoDoorCount != newTotal) {
        m_totalAutoDoorCount = newTotal;
        emit totalAutoDoorCountChanged();
    }
    if (m_onlineAutoDoorCount != onlineCount) {
        m_onlineAutoDoorCount = onlineCount;
        emit onlineAutoDoorCountChanged();
    }
}

void ResourceViewModel::updateCallerList()
{
    if (!m_mapService) {
        return;
    }

    QList<application::caller::CallerRuntimeInfo> aggregated;
    QSet<const application::caller::CallerManager*> visitedManagers;
    const auto floors = m_mapService->getLoadedFloors();
    for (int floor : floors) {
        auto manager = m_mapService->getCallerManager(floor);
        if (!manager) {
            continue;
        }

        auto* rawManager = manager.get();
        connectCallerManager(rawManager);

        if (visitedManagers.contains(rawManager)) {
            continue;
        }
        visitedManagers.insert(rawManager);

        const auto infos = manager->getCallerRuntimeInfos();
        for (const auto& info : infos) {
            aggregated.append(info);
        }
    }

    std::sort(aggregated.begin(), aggregated.end(), [](const application::caller::CallerRuntimeInfo& left,
                                                       const application::caller::CallerRuntimeInfo& right) {
        return left.callerNum < right.callerNum;
    });

    m_callerListModel->updateData(aggregated);

    const int newTotal = aggregated.count();
    const int newOnline = std::count_if(aggregated.begin(), aggregated.end(),
        [](const application::caller::CallerRuntimeInfo& info) { return info.isOnline; });

    if (m_totalCallerCount != newTotal) {
        m_totalCallerCount = newTotal;
        emit totalCallerCountChanged();
    }
    if (m_onlineCallerCount != newOnline) {
        m_onlineCallerCount = newOnline;
        emit onlineCallerCountChanged();
    }
}

void ResourceViewModel::connectCallerManager(application::caller::CallerManager* manager)
{
    if (!manager || m_connectedCallerManagers.contains(manager)) {
        return;
    }

    connect(manager, &application::caller::CallerManager::callerRuntimeInfoChanged,
            this, &ResourceViewModel::refreshCallerData,
            Qt::UniqueConnection);
    m_connectedCallerManagers.insert(manager);
}

void ResourceViewModel::connectAreaManager(application::area::AreaManager* manager)
{
    if (!manager || m_connectedAreaManagers.contains(manager)) {
        return;
    }

    connect(manager, &application::area::AreaManager::areaOccupationChanged,
            this, &ResourceViewModel::onAreaManagerSignal,
            Qt::UniqueConnection);
    m_connectedAreaManagers.insert(manager);
}

void ResourceViewModel::connectThirdAreaManager(application::third_area::ThirdAreaManager* manager)
{
    if (!manager || m_connectedThirdAreaManagers.contains(manager)) {
        return;
    }

    connect(manager, &application::third_area::ThirdAreaManager::areaOccupied,
            this, &ResourceViewModel::onThirdAreaSignal,
            Qt::UniqueConnection);
    connect(manager, &application::third_area::ThirdAreaManager::areaReleased,
            this, &ResourceViewModel::onThirdAreaSignal,
            Qt::UniqueConnection);
    m_connectedThirdAreaManagers.insert(manager);
}

} // namespace viewmodels
} // namespace presentation
